package cn.kmsoft.jssc.service.processor;

import java.util.*;

import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.jssc.config.AnalyseConfig;
import cn.kmsoft.jssc.entity.analyse.*;
import cn.kmsoft.jssc.service.AnalyseTaskProcessor;
import cn.kmsoft.wololo.object.query.GeoJsonQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;


/**
 * 三区三线的永久基本农田-空间套合叠加分析
 * 
 * @author wangq
 *
 */
public class YjjbntAnalyseTaskProcessor extends AnalyseTaskProcessor {
	private static final Logger logger = LoggerFactory.getLogger(YjjbntAnalyseTaskProcessor.class);
	//基本农田
	private final String analysePoint="yjjbnt";
	private AnalyseTaskParam analyseTaskParam;
	private AnalyseConfig analyseConfig;
	
	public YjjbntAnalyseTaskProcessor(AnalyseTaskParam param, AnalyseConfig analyseConfig) {
		this.analyseTaskParam=param;
		this.analyseConfig=analyseConfig; 
	}
	
	public AnalyseTaskParam getAnalyseTaskParam() {
		return analyseTaskParam;
	}
	public void setAnalyseTaskParam(AnalyseTaskParam analyseTaskParam) {
		this.analyseTaskParam = analyseTaskParam;
	}

	@Override
	public TaskResult call() throws Exception {
		// TODO Auto-generated method stub
		String threadId = Thread.currentThread().getName();
		
		String tableName = this.analyseTaskParam.getTableName();
		String analyseType=this.analyseTaskParam.getAnalystType();
		String dbKey = this.analyseTaskParam.getDbKey();
		int fgeo_wkid= this.analyseTaskParam.getFgeo_wkid();
		String feaTypePoint = analyseTaskParam.getFeaTypePoint();

		AnalyseDb analyseDb = this.analyseConfig.getAnalyseDbByDbkey(dbKey);
		if(analyseDb==null){
			System.out.println();
			String errorMsg = String.format("--->TaskProcessor stop, dbKey: %s, 为null",dbKey);
			System.out.println(errorMsg);
			logger.warn(errorMsg);

			return null;
		}
		String dbType = analyseDb.getDbType();
		String dbInstance = analyseDb.getDbInstance();
		String tablespace = analyseDb.getTablespace();
		String serverId = analyseDb.getServerId();//分析服务标识

		String tableId = dbInstance + "/" + tablespace + "." + tableName;
		//注意，根据数据库类型进行分类处置。
		//若为oracle的sde，则需要添加表空间；
		if("postgresql".equalsIgnoreCase(dbType)){
			//若为postgresql的postgis库，则去掉表空间或者为postgis_33_sample.sde.dltb_2018_500155_d36
			tableId = dbInstance + "/" + dbInstance+"."+ tablespace + "." + tableName;
		}
		String operatorMethod = "intersectpy";
		if(analyseType.equalsIgnoreCase("intersect") && feaTypePoint.equalsIgnoreCase("py")){
			operatorMethod = "intersectpy";
		}else if(analyseType.equalsIgnoreCase("intersect") && feaTypePoint.equalsIgnoreCase("py2")){
			operatorMethod = "intersectpy2";
		}else if(analyseType.equalsIgnoreCase("spatialquery") && feaTypePoint.equalsIgnoreCase("py")){
			operatorMethod = "spatialQuery";
		} else if(analyseType.equalsIgnoreCase("spatialquery") && feaTypePoint.equalsIgnoreCase("py2")){
			operatorMethod = "spatialQuery2";
		} else if(analyseType.equalsIgnoreCase("difference") && feaTypePoint.equalsIgnoreCase("py")){
			operatorMethod = "difference";
		}

		AnalyseServer analyseServer = this.analyseConfig.getAnalyseServerByServerId(serverId);
		String serverUrl = analyseServer.getServerUrl();

		String targetUrl = serverUrl + "/" + operatorMethod + "/" + tableId;
		//String targetUrl = this.analyseConfig.getServerUrl() + "/" + operatorMethod + "/" + tableId;
		//String targetUrl = this.analyseConfig.getServerUrl() + "/" + analyseType + "/" + tableId;
		
		//任务参数
		AnalyseTaskParam params = this.analyseTaskParam;
		params.setTargetUrl(targetUrl);
		
		TaskResult taskResult = this.startAnalyse(operatorMethod,threadId, params);

		return taskResult;
	}

	/**
	 * start分析
	 *
	 * TaskParam params
	 * Return
	 */
	@Override
	public TaskResult startAnalyse(String operatorMethod,String threadId, AnalyseTaskParam params) {
		TaskResult result = new TaskResult();

		String tableName= params.getTableName();
		String targetUrl = params.getTargetUrl();
		String jobId= params.getJobId();
		String taskId = params.getTaskId();
		String dkbh = params.getDkbh();
		GeoJsonQuery query = (GeoJsonQuery) params.getQuery();

		result.setThreadId(threadId);
		result.setJobId(jobId);
		result.setAnalystPoint(this.analysePoint);
		result.setProcessorName(params.getProcessName());
		result.setTaskId(taskId);
		result.setDkbh(dkbh);
		result.setTableName(tableName);

		System.out.println(String.format("--->doAnalyse,threadId: %s, jobId: %s, dkbh: %s, targetUrl: %s",threadId, jobId, dkbh, targetUrl));
		//叠加分析
		List<YjjbntDetailResult> yjjbntDetailList = this.doAnalyse(jobId,targetUrl, query);
		if(yjjbntDetailList.size()>0){
			YjjbntDetailResult detailResult=yjjbntDetailList.get(0);
			double sgeoarea = detailResult.getSgeoarea();
			result.setDkmj(sgeoarea);
		}

		System.out.println(String.format("--->threadId: %s, jobId: %s, analysePoint: %s, 基本农田占压分析的详细数量： %d", threadId, jobId,  this.analysePoint, yjjbntDetailList.size()));
		Map<String, Statis03Result> yjjbnt03Summary = this.summaryYjjbntStatis03Result(yjjbntDetailList);
		JbntZySummary01Result yjjbnt01Summary = this.summaryYjjbntStatis01Result(yjjbntDetailList);

		result.setDetailsListResult(yjjbntDetailList);
		result.setSummary03Result(yjjbnt03Summary);
		result.setSummary03DBEntResult(null);
		result.setSummary02Result(null);
		result.setSummary01Result(yjjbnt01Summary);

		return result;
	}
	
	
	/**
	 * 永久基本农田-占用分析
	 * 
	 * @param query
	 * @return
	 */
	public List<YjjbntDetailResult> doAnalyse(String jobId, String targetUrl, GeoJsonQuery query) {

		List<YjjbntDetailResult> yjjbntDetailList = new ArrayList<YjjbntDetailResult>();
		
		String queryJsonStr = JSONObject.toJSONString(query);
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		
		HttpEntity<String> entity = new HttpEntity<>(queryJsonStr, headers);
		
		//2、转发空间分析的请求
		ResponseEntity<JSONObject> exchange = this.exchangeSpatialAnalyst(jobId, targetUrl, entity);
		if(exchange==null){
			logger.error("转发后台spatialboot的请求发生异常，exchangeSpatialAnalyst返回为null");
			return yjjbntDetailList;
		}
		JSONObject jbntObject= exchange.getBody();
		if(jbntObject==null || jbntObject.getJSONArray("result")==null) {
			logger.error("转发后台spatialboot返回结果为空");
			return yjjbntDetailList;
		}
		
		JSONArray feasJSONArray =jbntObject.getJSONArray("result").getJSONObject(0).getJSONArray("features");
		//仅仅获取属性
		//List<Map<String,String>> allFeaProperties = this.parseFeaProperties(feasJSONArray);
		//获取图形和属性
		List<Map<String,String>> allFeaProperties = this.parseFeaGeometryAndProperties(feasJSONArray);
		int feaCount = allFeaProperties.size();		
		for(int i=0; i<feaCount;i++ ) {
			Map<String,String> feaProps = allFeaProperties.get(i);

			//将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
			Map<String,String> feaPropsKeyLowercCase = new HashMap<>();
			feaProps.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));

			//1-目标图层的字段值
			String bsm = feaPropsKeyLowercCase.get("bsm").toString();//BSM
			String yjjbnttbbh = feaPropsKeyLowercCase.get("yjjbnttbbh").toString();//永久基本农田图斑编号YJJBNTTBBH
			String dlbm = feaPropsKeyLowercCase.get("dlbm").toString();//DLBM
			String dlmc = feaPropsKeyLowercCase.get("dlmc").toString();//DLMC
			double yjjbnt_tbmj = Double.parseDouble(feaPropsKeyLowercCase.get("yjjbnttbmj").toString());//几何面积YJJBNTTBMJ
			double yjjbnt_mj = Double.parseDouble(feaPropsKeyLowercCase.get("yjjbntmj").toString());//字段净面积YJJBNTMJ

			//2-追加的3个几何面积
			double area = Double.parseDouble(feaPropsKeyLowercCase.get("area").toString());//叠加后重叠范围的几何面积AREA
			double fgeoarea = Double.parseDouble(feaPropsKeyLowercCase.get("fgeoarea").toString());//目标图层（sde库）原图斑几何面积FGEOAREA
			double sgeoarea = Double.parseDouble(feaPropsKeyLowercCase.get("sgeoarea").toString());//上传图斑的几何面积SGEOAREA

			double tkmj = 0.0;//田坎面积
			String kcdlbm = feaPropsKeyLowercCase.get("kcdlbm").toString();//扣除地类编码KCDLBM
			double kcxs = Double.parseDouble( !StringUtil.isNullOrEmpty(feaPropsKeyLowercCase.get("kcxs")) ? feaPropsKeyLowercCase.get("kcxs").toString():"0.0");//扣除系数KCXS
			double kcmj_field = Double.parseDouble( !StringUtil.isNullOrEmpty(feaPropsKeyLowercCase.get("kcmj")) ? feaPropsKeyLowercCase.get("kcmj").toString():"0.0");//扣除面积KCMJ
			String gdlx = feaPropsKeyLowercCase.get("gdlx").toString();//耕地类型GDLX
			String gdpdjb = feaPropsKeyLowercCase.get("gdpdjb").toString();//耕地坡度级别GDPDJB

			double percent = area/fgeoarea;
			double adjustPercent = percent< 1.0 ? percent : 1.0;
			double kchmj = yjjbnt_mj * adjustPercent;//净面积
			//double kcmj = area * kcxs;//扣除面积
			double kcmj = kcmj_field * adjustPercent;//扣除面积

			//田坎
			if("1203".equalsIgnoreCase(kcdlbm)){
				tkmj = kcmj;
			}

			//3-叠加相交结果的几何图形
			String geomText = feaPropsKeyLowercCase.get("geom").toString();
			
			YjjbntDetailResult yjjbntDetail = new YjjbntDetailResult();
			yjjbntDetail.setFeaProps(feaProps);

			yjjbntDetail.setBsm(bsm);
			yjjbntDetail.setYjjbnt_tbbh(yjjbnttbbh);
			yjjbntDetail.setTbbh(yjjbnttbbh);
			yjjbntDetail.setDlbm(dlbm);
			yjjbntDetail.setMc(dlmc);

			//属性面积
			yjjbntDetail.setYjjbnt_sxmj( Math.abs(yjjbnt_mj));//属性面积（应该是扣除系数之后的字段净面积）
			yjjbntDetail.setYjjbnt_jhmj( Math.abs(yjjbnt_tbmj));//几何面积（字段几何面积）
			//新增的几何面积
			yjjbntDetail.setFgeoarea(Math.abs(fgeoarea));//目标图层（sde库）原图斑几何面积
			yjjbntDetail.setSgeoarea(Math.abs(sgeoarea));//上传图斑几何面积
			yjjbntDetail.setArea( Math.abs(area) );	//套合相交几何面积
			yjjbntDetail.setKcarea(kcmj);//扣除面积
			yjjbntDetail.setTkarea(tkmj);//田坎面积
			yjjbntDetail.setKcharea(kchmj);//扣除后的净面积

			yjjbntDetail.setGeomText(geomText);//图形

			yjjbntDetailList.add(yjjbntDetail);
		}
		
	    return yjjbntDetailList;
	}
	
	/**
	 * 基本农田-占用情况汇总
	 * 
	 * @param jbntZyDetailList
	 * @return
	 */
	public JbntZySummary01Result summaryYjjbntStatis01Result(List<YjjbntDetailResult> jbntZyDetailList) {
		double gdmj_sum =0.0;//耕地净面积
		double stmj_sum =0.0;//水田净面积,需要特殊出来
		double tkmj_sum =0.0;//田坎面积
		double qtmj_sum =0.0;//其他

		double xjmj_sum =0.0;//小计
		double gjmj_sum =0.0;//共计
		double jhmj_sum =0.0;//几何面积
		
		Iterator<YjjbntDetailResult> iter= jbntZyDetailList.iterator();
		while(iter.hasNext()) {
			YjjbntDetailResult jbntZyDetail = iter.next();
			
			String dlbm = jbntZyDetail.getDlbm();//地类编码
			double area = jbntZyDetail.getArea();//叠加几何面积
			double kchmj = jbntZyDetail.getKcharea();//扣除后净面积
			double tkmj = jbntZyDetail.getTkarea();//田坎面积
			double jhArea = jbntZyDetail.getYjjbnt_jhmj();//几何面积，在arcmap中计算的面积
			double sxArea = jbntZyDetail.getYjjbnt_sxmj();//属性面积，图斑面积的基础之上扣除了零星地物，线性地物，田坎系数等之后的

			//很重要，叠加相交面积与原图斑的字段几何计算面积的比例
			if("011".equalsIgnoreCase(dlbm) || "0101".equalsIgnoreCase(dlbm)) {
				//水田=011
				stmj_sum += kchmj;
			}

			if(this.analyseConfig.getTdlyfldmConfig().getTdlyxzfldm_gd().contains(dlbm) || this.analyseConfig.getTdlyfldmConfig().getTdlyxzfldm_gd_sd().contains(dlbm)) {
				//耕地=水田/旱地/水浇地
				gdmj_sum += kchmj;
			}else {
				qtmj_sum += kchmj;
			}
			tkmj_sum += tkmj;//田坎面积
			jhmj_sum += area;//几何面积
		}
		xjmj_sum = gdmj_sum + qtmj_sum;
		gjmj_sum =xjmj_sum;
		
		JbntZySummary01Result jbntZySummary = new JbntZySummary01Result();
		jbntZySummary.setGdmj(gdmj_sum);//耕地面积
		jbntZySummary.setStmj(stmj_sum);//水田面积
		jbntZySummary.setTkmj(tkmj_sum);//田坎面积
		jbntZySummary.setQtmj(qtmj_sum);
		jbntZySummary.setXjmj(xjmj_sum);
		jbntZySummary.setGjmj(gjmj_sum);
		
		return jbntZySummary;
	}

	/**
	 * 对永久基本农田按类型代码进行面积汇总至3级类
	 *
	 * @param jbntDetailResultList
	 * @return
	 */
	public Map<String,Statis03Result> summaryYjjbntStatis03Result(List<YjjbntDetailResult> jbntDetailResultList) {
		Map<String, Statis03Result> jbntStatisResults = new HashMap<String, Statis03Result>();
		// 汇总为三级分类统计
		Iterator<YjjbntDetailResult> detailIter = jbntDetailResultList.iterator();
		while (detailIter.hasNext()) {
			YjjbntDetailResult jbnt = detailIter.next();
			String dlbm = jbnt.getDlbm();
			String dlmc = jbnt.getBsm();

			double jhArea = jbnt.getArea();
			double tkArea = jbnt.getTkarea();
			double kcArea = jbnt.getKcarea();
			double kchArea = jbnt.getKcharea();

			//判断基本农田的类型代码
			if (jbntStatisResults.containsKey(dlbm)) {
				Statis03Result statis03Result = jbntStatisResults.get(dlbm);
				double areaOfSum = statis03Result.getAnalyseArea();
				double kchAreaOfSum = statis03Result.getKchArea();
				double tkAreaOfSum = statis03Result.getTkArea();
				double kcAreaOfSum = statis03Result.getKcArea();

				statis03Result.setAnalyseArea(areaOfSum + jhArea);
				statis03Result.setKcArea(kcAreaOfSum+kcArea);
				statis03Result.setTkArea(tkAreaOfSum+tkArea);
				statis03Result.setKchArea(kchAreaOfSum+kchArea);
			} else {
				Statis03Result statis03Result = new Statis03Result();
				statis03Result.setDm(dlbm);
				statis03Result.setMc(dlmc);
				statis03Result.setAnalyseArea(kchArea);
				statis03Result.setTkArea(tkArea);
				statis03Result.setKchArea(kchArea);
				statis03Result.setKcArea(kcArea);

				jbntStatisResults.put(dlbm, statis03Result);
			}
		}

		return jbntStatisResults;
	}
	
}
